package tech.mhuang.pacebox.springboot.autoconfiguration.trace.webclient;

import com.alibaba.fastjson.JSON;
import io.opentracing.Span;
import io.opentracing.contrib.spring.web.client.WebClientSpanDecorator;
import io.opentracing.tag.Tags;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import tech.mhuang.pacebox.core.exception.ExceptionUtil;

import java.util.HashMap;
import java.util.Map;

/**
 * 埋点webClient
 *
 * @author mhuang
 * @since 1.0.0
 */
public class TraceWebClientSpanDecorator implements WebClientSpanDecorator {
    static final String COMPONENT_NAME = "java-spring-webclient";

    @Override
    public void onRequest(final ClientRequest clientRequest, final Span span) {
        Tags.COMPONENT.set(span, COMPONENT_NAME);
        Tags.HTTP_URL.set(span, clientRequest.url().toString());
        Tags.HTTP_METHOD.set(span, clientRequest.method().toString());
        span.setTag("request.header", JSON.toJSONString(clientRequest.headers()));
        span.setTag("request.cookie", JSON.toJSONString(clientRequest.cookies()));
        span.setTag("request.param", JSON.toJSONString(clientRequest.url().getQuery()));
        //TODO 加入发送数据埋点
        if (clientRequest.url().getPort() != -1) {
            Tags.PEER_PORT.set(span, clientRequest.url().getPort());
        }
    }

    @Override
    public void onResponse(final ClientRequest clientRequest, final ClientResponse clientResponse, final Span span) {
        Tags.HTTP_STATUS.set(span, clientResponse.rawStatusCode());
        //TODO 加入应答数据埋点
    }

    @Override
    public void onError(final ClientRequest clientRequest, final Throwable throwable, final Span span) {
        Tags.ERROR.set(span, Boolean.TRUE);
        span.log(errorLogs(throwable));
    }

    @Override
    public void onCancel(final ClientRequest httpRequest, final Span span) {
        final Map<String, Object> logs = new HashMap<>(2);
        logs.put("event", "cancelled");
        logs.put("message", "The subscription was cancelled");
        span.log(logs);
    }

    static Map<String, String> errorLogs(final Throwable throwable) {
        Map<String, String> errorLogs = ExceptionUtil.logsForException(throwable);
        errorLogs.put("event", Tags.ERROR.getKey());
        return errorLogs;
    }
}
